<?php
/**
 * Created by PhpStorm.
 * User: joe
 * Date: 2019-12-11
 * Time: 11:27
 */

namespace app\common\bean\builder;


use app\common\bean\ListMap;
use app\common\bean\TableBean;

abstract class BaseBuilder
{
    protected $beanBean = null;
    protected $tableList = null;//数据库中的所有表

    /** 获取php头 作者名
     * @param string $author
     * @return string
     */
    protected function getPhpHeader($author = "joe")
    {
        return "<?php{$this->getEnter()}/*由bean脚本生成 powerBy--{$author}*/";
    }

    /** 获取命名空间
     * @param string $latsPackage
     * @param string $middlePackage
     * @return string
     */
    protected function getAppNamespace($latsPackage = "bean", $middlePackage = "\common\\")
    {
        $appNamespace = config("app_namespace", 'app');//获取命名空间开头  app
        return "namespace {$appNamespace}{$middlePackage}{$latsPackage};";//命名空间
    }

    /** 生成引用的use
     * @param $latsPackage
     * @param string $module
     * @return string
     */
    protected function getModuleUsePackage($latsPackage, $module = 'common')
    {
        $appNamespace = config("app_namespace", 'app');//获取命名空间开头  app
        return "use {$appNamespace}\\{$module}\\{$latsPackage};";
    }

    /** 获取class名
     * @param $fileName
     * @param $parents
     * @param bool $isInterface
     * @return string
     */
    protected function getClassExtends($fileName, $parents, $isInterface = false)
    {
        $impType = !$isInterface ? 'extends' : 'implements';
        return "class {$fileName} {$impType} {$parents}{$this->getEnter()}{{$this->getEnter()}";//类名及基层基础Bean类
    }

    /** 根据文件名获取单例字符串
     * @param $fileName
     * @return string
     */
    protected function getInstanceString($fileName)
    {
        /*return (new StringBuilder())->concatStringEnter("protected static \$_self = null;",1,2)
            ->concatStringEnter("static function getInstance(){",1)
            ->concatStringEnter("if(empty(self::\$_self)){",2)
            ->concatStringEnter("self::\$_self = new {$fileName}();",3)
            ->concatStringEnter("}",2)
            ->concatStringEnter("return self::\$_self;",2)
            ->concatStringEnter("}")
            ->getContent()
            ;*/
        return (new StringBuilder())->concatStringEnter("/**",1)
            ->concatStringEnter("* @return {$fileName}",1)
            ->concatStringEnter("*/",1)
            ->concatStringEnter("static function getInstance(){",1)
            ->concatStringEnter("return parent::getInstance();",2)
            ->concatStringEnter("}")
            ->getContent();

    }

    /** 生成todo
     * @param string $content
     * @return string
     */
    protected function getToDo($content = "// Todo:添加业务处理代码...")
    {
        return "{$content}{$this->getEnter(2)}";
    }

    /** 生成制表符
     * @param int $count
     * @return string
     */
    protected function getTab($count = 1)
    {
        return str_repeat("\t", $count);
    }

    /** 生成回车符
     * @param int $count
     * @return string
     */
    protected function getEnter($count = 1)
    {
        return str_repeat("\n", $count);
    }

    /** 获取table列表
     * @return mixed
     */
    public function getTableList()
    {
        return $this->tableList;
    }

    /**
     * @param $ROOT_PATH
     * @param $tableName
     * @param $suffix
     * @param string $module
     * @return bool
     */
    private function checkGenerateFileExist($ROOT_PATH, $tableName, $suffix,$module='/common/')
    {
        $commonBeanRoot = $ROOT_PATH . $module . strtolower($suffix) . "/";//manage类存放的文件夹
        $fileName = $this->getFileName($tableName, $suffix);
        $fileRoot = $commonBeanRoot . $fileName . ".php";
        return is_file($fileRoot);
    }

    /** 获取对应后缀文件名
     * @param        $tableName
     * @param string $suffix
     * @param string $fileSuffix
     * @return string
     */
    protected function getFileName($tableName, $suffix = "Bean", $fileSuffix = "")
    {
        $prefix = config("database.prefix");
        $fileArray = explode("_", $tableName);
        $fileName = '';
        if (!empty($prefix)) {
            foreach ($fileArray as $key => $value) {
                if ($key != 0) {
                    $fileName .= ucfirst($value);
                }
            }
        } else {
            foreach ($fileArray as $key => $value) {
                $fileName .= ucfirst($value);
            }
        }
        $fileName = $fileName . $suffix; //bean 文件名
        !strlen($fileSuffix) ?: $fileName .= $fileSuffix;
        return $fileName;
    }

    /** 获取生成文件的详情
     * @param TableBean $tableBean
     * @return string
     */
    public function getFilesInfo(TableBean $tableBean)
    {
        $listMap = new ListMap();
        $tables = $this->getTableList();
        if (!in_array($tableBean->getTableName(), $tables->getData())) {
            return 'error - table not exit';
        } else {
            $ROOT_PATH = dirname(dirname(dirname(dirname(__FILE__))));
            $listMap->setParameter("bean", $this->checkGenerateFileExist($ROOT_PATH, $tableBean->getTableName(), "Bean"));
            $listMap->setParameter("model", $this->checkGenerateFileExist($ROOT_PATH, $tableBean->getTableName(), "Model"));
            $listMap->setParameter("validate", $this->checkGenerateFileExist($ROOT_PATH, $tableBean->getTableName(), "Validate"));
            $listMap->setParameter("manager", $this->checkGenerateFileExist($ROOT_PATH, $tableBean->getTableName(), "Manage"));
            $listMap->setParameter("controller", $this->checkGenerateFileExist($ROOT_PATH, $tableBean->getTableName(), "Controller",'/admin/'));
        }
        return $listMap->getData();
    }

    /** 获取生成文件的详情
     * @param TableBean $tableBean
     * @return string
     */
    public function getAllColumn(TableBean $tableBean)
    {
        $tables = $this->getTableList();
        if (!in_array($tableBean->getTableName(), $tables->getData())) {
            return 'error - table not exit';
        } else {
            return $this->beanBean->getTableColumn($tableBean->getTableName())->getList();
        }
    }

    /** 获取表字段列表给form表单使用
     * @param TableBean $tableBean
     * @return string
     */
    public function getAllColumnForForm(TableBean $tableBean, $sence = 'create')
    {
        $columns = $this->getAllColumn($tableBean);
        foreach ($columns as $key => &$item) {
            $item['notNull'] = true;

            if ($sence == 'create' && $item['COLUMN_KEY'] == 'PRI') unset($columns[$key]);

            if ($item['DATA_TYPE'] == 'int' || $item['DATA_TYPE'] == 'varchar') {
                $item['formType'] = 'input';
            } else if ($item['DATA_TYPE'] == 'tinyint') {
                $item['formType'] = 'select';
            } else if ($item['DATA_TYPE'] == 'text' || $item['DATA_TYPE'] == 'longtext') {
                $item['formType'] = 'textarea';
            } else {
                unset($columns[$key]);
            }
        }

        return array_values($columns);
    }

    /**
     * @param TableBean $tableBean
     * @return ListMap
     * @throws \ReflectionException
     */
    public function getEnumFields(TableBean $tableBean)
    {
        $tableColumns = $this->getAllColumn($tableBean);
        $commonBeanRoot = "app\\common\\enum\\";//bean类存放的文件夹
        $listMap = new ListMap();
        $fieldsArr = array();
        $selectArr = array();
        foreach ($tableColumns as $tableColumn) {
            #不满足四种类型或者主键，唯一索引的都不能创建枚举类
            if ($tableColumn['DATA_TYPE'] != 'tinyint' && $tableColumn['DATA_TYPE'] != 'int' || $tableColumn['COLUMN_KEY'] == 'UNI' || $tableColumn['COLUMN_KEY'] == 'PRI') {
                $fieldsArr[] = ['value' => $tableColumn['COLUMN_NAME'], 'title' => $tableColumn['COLUMN_NAME'], "disabled" => true];
                continue;
            } else {
                $enumItem = ['value' => $tableColumn['COLUMN_NAME'], 'title' => $tableColumn['COLUMN_NAME']];

                $fieldName = $tableBean->getTableName() . "_" . $tableColumn['COLUMN_NAME'];
                $fileName = $this->getFileName($fieldName, 'Enum');
                $fileRoot = $commonBeanRoot . $fileName;
                if (class_exists($fileRoot)) {
                    $ref = new \ReflectionClass($fileRoot);//Class1 可以为对象实例 $class = new Class();
                    # Todo 暂时无法解决枚举text获取的问题
                    $method = $ref->getMethod("getArrayName");
                    $constP = $ref->getConstants();
                    if ($constP) {
                        $enumItem['kvList'] = array();
                        foreach ($constP as $key => $value) {
                            array_push($enumItem['kvList'], ['key' => $key, 'value' => $value]);
                        }
                    }
                }
                $fieldsArr[] = $enumItem;
            }
            if ($tableColumn['DATA_TYPE'] == 'tinyint') {
                $selectArr[] = $tableColumn['COLUMN_NAME'];
            }
        }
        $listMap->setParameter("fieldsArr", $fieldsArr);
        $listMap->setParameter("selectArr", $selectArr);
        return $listMap;
    }

}